﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

#region Usings

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.TeamFoundation.Server;
using ScrumTable.Common;
using ScrumTable.Common.Net;
using ScrumTable.Common.Text;

#endregion

namespace ScrumTable.DL.Data.TFS.Services.TeamFoundation
{
    /// <summary>
    /// Specifies a registration handler which is used to search for the
    /// appropriate service registration entries of WSS and RS services.
    /// </summary>
    /// <remarks>
    /// General link about tfs web services:
    ///  http://abadawi.blogspot.com/2008/11/tfs-2008-web-services-list.html
    /// 
    /// Registration service url:
    ///  http://ba-tfssurface:8080/tfs/Services/v1.0/Registration.asmx?op=GetRegistrationEntries
    /// </remarks>
    public class TfsRegistrationLoader
    {
        #region Declarations
        //--------------------------------------------------------------------
        // Declarations
        //--------------------------------------------------------------------

        private const string TeamProjectsRegistration = "TeamProjects";
        private const string ReportsMapping = "ReportServer";
        
        private const string ReportsRegistration = "Reports";
        private const string ReportsRegistrationPostfix = ":ReportFolder";
        private const string ReportsServerBaseReportsUrl = "ReportWebServiceUrl";

        private const string WssRegistrationPostfix = ":Portal";

        private readonly IRegistration _regSvc;
        private readonly RegistrationEntry[] _teamProjects;
        private readonly RegistrationEntry[] _reports;

        #endregion

        #region Properties
        //--------------------------------------------------------------------
        // Properties
        //--------------------------------------------------------------------

        #endregion

        #region Constructors / Destructor
        //--------------------------------------------------------------------
        // Constructors / Destructor
        //--------------------------------------------------------------------

        /// <summary>
        /// Creates a new TfsRegistrationLoader instance, no public constructor
        /// needed.
        /// </summary>
        public TfsRegistrationLoader(IRegistration regSvc)
        {
            PreCondition.AssertNotNull(regSvc, "regSvc");

            _regSvc = regSvc;
            _teamProjects = _regSvc.GetRegistrationEntries(TeamProjectsRegistration);
            _reports = _regSvc.GetRegistrationEntries(ReportsRegistration);
        }

        #endregion

        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------

        /// <summary>
        /// Gets a dictionary of [projectName : string] -> [url : Uri] which
        /// contains the sharepoint server urls.
        /// </summary>
        public IDictionary<string, ServiceRegistration> GetSharepointServerUris()
        {
            IDictionary<string, ServiceRegistration> registrationEntries = new Dictionary<string, ServiceRegistration>();

            /* --- Retrieve WSS service url ---
             *
             * WSS explanation:
             *  http://blog.hinshelwood.com/archive/2007/05/31/team-foundation-server-amp-sharepoint-3.0.aspx
             *  
             * Format:
             *  <FrameworkRegistrationEntry>
             *   <Type>TeamProjects</Type>
             *   <ServiceInterfaces>
             *    <ServiceInterface>
             *     <Name>TFSSurfaceCollaboration:Portal</Name> 
             *     <Url>http://ba-tfssurface/sites/DefaultCollection/TFSSurfaceCollaboration</Url> 
             *    </ServiceInterface>
             *   </ServiceInterfaces>
             *  </FrameworkRegistrationEntry>
             */
            foreach (ServiceInterface svcLocation in GetTeamProjectServiceInterface(WssRegistrationPostfix))
            {
                Uri wssRegUri;

                if (Uri.TryCreate(svcLocation.Url, UriKind.RelativeOrAbsolute, out wssRegUri))
                {
                    registrationEntries.Add(
                        svcLocation.Name.TrimEnd(WssRegistrationPostfix),
                        new ServiceRegistration(wssRegUri));
                }
            }
            return registrationEntries;
        }

        /// <summary>
        /// Gets a dictionary of [projectName : string] -> [url : Uri] which
        /// contains the reporting server urls.
        /// </summary>
        public IDictionary<string, ServiceRegistration> GetReportingServerUris()
        {
            IDictionary<string, ServiceRegistration> registrationEntries = new Dictionary<string, ServiceRegistration>();

            /* --- Retrieve reporting service url ---
             *
             * Format:
             *  <FrameworkRegistrationEntry>
             *   <Type>Reports</Type>
             *   <ServiceInterfaces>
             *    <ServiceInterface>
             *     <Name>ReportWebServiceUrl</Name> 
             *     <Url>http://ba-tfssurface/ReportServer/ReportService2005.asmx</Url> 
             *    </ServiceInterface>
             *   </ServiceInterfaces>
             *  </FrameworkRegistrationEntry>
             *  
             *  <FrameworkRegistrationEntry>
             *   <Type>TeamProjects</Type>
             *   <ServiceInterfaces>
             *    <ServiceInterface>
             *     <Name>TFSSurfaceCollaboration:ReportFolder</Name> 
             *     <Url>/TfsReports/DefaultCollection/TFSSurfaceCollaboration</Url> 
             *    </ServiceInterface>
             *   </ServiceInterfaces>
             *  </FrameworkRegistrationEntry>
             */
            Uri reportServiceUri = GetReportsServiceUrl();

            if (reportServiceUri != null)
            {
                Uri reportingServerBaseUri = GetReportsRenderUrl(reportServiceUri);

                if (reportingServerBaseUri != null)
                {
                    foreach (ServiceInterface svcLocation in GetTeamProjectServiceInterface(ReportsRegistrationPostfix))
                    {
                        registrationEntries.Add(
                            svcLocation.Name.TrimEnd(ReportsRegistrationPostfix),
                            new ServiceRegistration(
                                reportingServerBaseUri.CombineQueryAsPath(svcLocation.Url),
                                reportServiceUri));
                    }
                }
            }
            return registrationEntries;
        }

        private IEnumerable<ServiceInterface> GetTeamProjectServiceInterface(string postfix)
        {
            return (from entry in _teamProjects
                    from service in entry.ServiceInterfaces
                    where service.Name.EndsWith(postfix)
                    select service);
        }

        private Uri GetReportsServiceUrl()
        {
            string reportsServiceUrl = (from entry in _reports
                                        from service in entry.ServiceInterfaces
                                        where service.Name == ReportsServerBaseReportsUrl
                                        select service.Url).FirstOrDefault();

            if (!string.IsNullOrEmpty(reportsServiceUrl))
            {
                return new Uri(reportsServiceUrl);
            }
            return null;
        }

        private Uri GetReportsRenderUrl(Uri reportsWebService)
        {
            if (reportsWebService != null)
            {
                string reportsWebServiceUrl = reportsWebService.GetLeftPart(UriPartial.Authority);

                if (reportsWebServiceUrl.EndsWith("/"))
                    reportsWebServiceUrl += ReportsMapping;
                else
                    reportsWebServiceUrl += "/" + ReportsMapping;

                Uri newServerUri;

                if (Uri.TryCreate(reportsWebServiceUrl, UriKind.RelativeOrAbsolute, out newServerUri))
                {
                    return newServerUri;
                }
            }
            return null;
        }

        #endregion

        #region Events
        //--------------------------------------------------------------------
        // Events
        //--------------------------------------------------------------------

        #endregion
    }
}